package edu.cs.usask.ca.silver.plugin.rcp.dialogs.create;

import java.io.File;

import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.DirectoryDialog;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.List;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;

import edu.cs.usask.ca.silver.businesslogic.ids.ModelProjectID;

/**
 * 
 * A new Dialog class that allows user to create an empty Model Version to
 * database. The Model Version name, description and creator should not be
 * blank. The class provides getter methods to provide inputs from all fields.
 * 
 * 
 * @author Yudi Xue
 * 
 */

public class CreateModelVersionDialog extends Dialog {

	// private Text modelProjectIdText;
	private Text modelVersionNameText;
	private Text modelVersionCreatorText;
	private Text modelVersionDescriptionText;
	private Text sourceFileText;
	private Text jarFileText;
	private List files;

	// private String modelProjectId;
	private final ModelProjectID modelprojectid;
	private Combo packageType;
	private String modelVersionName;
	private String modelVersionCreator;
	private String modelVersionDescription;
	private String sourceFile;
	private String jarFile;
	private Boolean selected = true;
	private Boolean selectedAssociates = true;
	private String[] associateFiles;

	public CreateModelVersionDialog(Shell parentShell,
			ModelProjectID selectedParentProjectIDFromProjectView) {
		super(parentShell);
		setShellStyle(SWT.DIALOG_TRIM | SWT.RESIZE);
		modelprojectid = selectedParentProjectIDFromProjectView;
	}

	@Override
	protected void configureShell(Shell newShell) {
		super.configureShell(newShell);
		newShell.setText("Create New Model Version");
	}

	@Override
	protected Control createDialogArea(Composite parent) {
		final Composite composite = new Composite(parent, SWT.NONE);
		composite.setLayout(new GridLayout(3, false));

		GridData gridData = new GridData();

		// +++++ Added packagetype specification for AnyLogic and Vensim
		// Label modelVersionTypeLabel = new Label(composite, SWT.NONE);
		// modelVersionTypeLabel.setText("&Package Type:");
		// gridData = new GridData();
		// gridData.verticalAlignment = SWT.TOP;
		// modelVersionTypeLabel.setLayoutData(gridData);
		//
		// packageType = new Combo(composite, SWT.NONE);
		// packageType.setItems(new String[] {"AnyLogic", "Vensim"});
		// gridData = new GridData();
		// //gridData.horizontalSpan = 2;
		// gridData.horizontalAlignment = SWT.FILL;
		// gridData.grabExcessHorizontalSpace = true;
		// packageType.setLayoutData(gridData);
		// -------

		Label modelVersionNameLabel = new Label(composite, SWT.NONE);
		modelVersionNameLabel.setText("&Version Name");

		modelVersionNameText = new Text(composite, SWT.BORDER);
		gridData.horizontalAlignment = SWT.FILL;
		gridData.grabExcessHorizontalSpace = true;
		gridData.horizontalSpan = 2;
		modelVersionNameText.setLayoutData(gridData);

		Label modelVersionCreatorLabel = new Label(composite, SWT.NONE);
		modelVersionCreatorLabel.setText("&Version Creator:");
		gridData = new GridData();
		gridData.verticalAlignment = SWT.TOP;
		modelVersionCreatorLabel.setLayoutData(gridData);

		modelVersionCreatorText = new Text(composite, SWT.BORDER);
		gridData = new GridData();
		gridData.horizontalAlignment = SWT.FILL;
		gridData.grabExcessHorizontalSpace = true;
		gridData.horizontalSpan = 2;
		modelVersionCreatorText.setLayoutData(gridData);
		modelVersionCreatorText.setText(System.getProperty("user.name"));

		Label modelVersionDescriptionLabel = new Label(composite, SWT.NONE);
		modelVersionDescriptionLabel.setText("&Version Description:");
		gridData = new GridData();
		gridData.verticalAlignment = SWT.TOP;
		modelVersionDescriptionLabel.setLayoutData(gridData);

		modelVersionDescriptionText = new Text(composite, SWT.BORDER | SWT.WRAP
				| SWT.MULTI);
		gridData = new GridData();
		gridData.horizontalAlignment = SWT.FILL;
		gridData.grabExcessHorizontalSpace = true;
		gridData.minimumHeight = modelVersionDescriptionText.getLineHeight() * 5;
		gridData.grabExcessVerticalSpace = true;
		gridData.horizontalSpan = 2;
		modelVersionDescriptionText.setLayoutData(gridData);

		// Below to specify input files.

		Group inputFilesGroup = new Group(composite, SWT.NONE);
		inputFilesGroup.setText("Input Files");
		gridData = new GridData();
		gridData.verticalIndent = 10;
		gridData.horizontalSpan = 3;
		inputFilesGroup.setLayoutData(gridData);
		inputFilesGroup.setLayout(new GridLayout(3, false));

		// check box
		final Button checkBox = new Button(inputFilesGroup, SWT.CHECK);
		checkBox.setText("&Create from user input file.");
		checkBox.setSelection(false);
		gridData = new GridData();
		gridData.horizontalSpan = 3;
		checkBox.setLayoutData(gridData);

		// Load Source file
		final Label sourceFileLabel = new Label(inputFilesGroup, SWT.END);
		gridData = new GridData();
		gridData.horizontalAlignment = SWT.END;
		sourceFileLabel.setLayoutData(gridData);
		sourceFileLabel.setText("&Source File:");

		sourceFileText = new Text(inputFilesGroup, SWT.BORDER);
		gridData = new GridData();
		gridData.widthHint = convertHeightInCharsToPixels(20);
		sourceFileText.setLayoutData(gridData);

		final Button getSourceFile = new Button(inputFilesGroup, SWT.PUSH
				| SWT.RIGHT | SWT.MouseUp);
		getSourceFile.setAlignment(SWT.CENTER);
		getSourceFile.setText("Browse");

		getSourceFile.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				// TODO multiple file and absolute path
				FileDialog file = new FileDialog(composite.getShell(), SWT.OPEN);
				file.setFilterExtensions(new String[] { "*.alp", "*.vpm" });
				file.setFilterPath(System.getProperty("user.home"));

				file.setFilterNames(new String[] { ".alp (AnyLogic Project)",
						".vpm (Vensim Packaged Model)" });
				file.setText("Open Model Source File:");
				sourceFileText.setText(file.open());
			}
		});

		// Load Jarfile
		final Label jarFileLabel = new Label(inputFilesGroup, SWT.NONE);
		gridData = new GridData();
		gridData.horizontalAlignment = SWT.END;
		jarFileLabel.setLayoutData(gridData);
		jarFileLabel.setText("&Input File:");
		jarFileLabel
				.setToolTipText("&Folder containing compiled class files in your "
						+ "AnyLogicWorkspace folder, usually named YOUR_SIMULATION_PACKAGE_BUILD/");

		jarFileText = new Text(inputFilesGroup, SWT.BORDER);
		gridData = new GridData();
		gridData.widthHint = convertHeightInCharsToPixels(20);
		jarFileText.setLayoutData(gridData);

		final Button getJarFile = new Button(inputFilesGroup, SWT.PUSH
				| SWT.RIGHT);
		getJarFile.setAlignment(SWT.CENTER);
		getJarFile.setText("Browse");
		getJarFile.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				// TODO multiple file and absolute path
				DirectoryDialog file = new DirectoryDialog(composite.getShell()
						.getShell(), SWT.OPEN);

				// Constraint the path to AnyLogicWorkspace
				file.setFilterPath(System.getProperty("user.home")
						+ System.getProperty("file.separator")
						+ "AnyLogicWorkspace");

				// If not appeared, set AnyLogicWorkspacePro
				if (file.getFilterPath() == null) {
					file.setFilterPath(System.getProperty("user.home")
							+ System.getProperty("file.separator")
							+ "AnyLogicWorkspacePro");
				}

				// Set to user.home if none of AnyLogic standard or pro
				// workspace is presented.
				if (file.getFilterPath() == null) {
					file.setFilterPath(System.getProperty("user.home"));
				}

				file.setText("Choose the FOLDER of compiled .class files: (*AnyLogic only)");
				jarFileText.setText(file.open());

			}
		});

		getSourceFile.setEnabled(checkBox.getSelection());
		getJarFile.setEnabled(checkBox.getSelection());
		sourceFileText.setEnabled(checkBox.getSelection());
		jarFileText.setEnabled(checkBox.getSelection());
		selected = checkBox.getSelection();
		
		/*
		 * Use check box to control whether user wants to add file with Project
		 */
		checkBox.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				getSourceFile.setEnabled(checkBox.getSelection());
				getJarFile.setEnabled(checkBox.getSelection());
				sourceFileText.setEnabled(checkBox.getSelection());
				jarFileText.setEnabled(checkBox.getSelection());
				selected = checkBox.getSelection();
			}
		});

		// Associate Files

		Group associateFilesGroup = new Group(composite, SWT.NONE);
		associateFilesGroup.setText("Associate Files");
		gridData = new GridData();
		gridData.verticalIndent = 10;
		gridData.horizontalSpan = 3;
		gridData.horizontalAlignment = SWT.FILL;
		associateFilesGroup.setLayoutData(gridData);
		associateFilesGroup.setLayout(new GridLayout(3, true));

		final Button associateFileCheckBox = new Button(associateFilesGroup,
				SWT.CHECK);
		associateFileCheckBox.setText("&Create with associate files.");
		associateFileCheckBox.setSelection(false);
		gridData = new GridData();
		gridData.horizontalSpan = 3;
		associateFileCheckBox.setLayoutData(gridData);

		final Label associateFileLabel = new Label(associateFilesGroup, SWT.END);
		associateFileLabel.setText("&List of associated files:");

		// Multiple-selection list
		files = new List(associateFilesGroup, SWT.MULTI | SWT.BORDER
				| SWT.V_SCROLL | SWT.H_SCROLL);
		gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
		gridData.horizontalSpan = 3;
		files.setLayoutData(gridData);

		final Label listCountLabel = new Label(associateFilesGroup, SWT.LEFT);
		listCountLabel.setText(String.valueOf(files.getItemCount())
				+ " files added.");

		final Button removeFile = new Button(associateFilesGroup, SWT.PUSH
				| SWT.RIGHT);
		removeFile.setAlignment(SWT.CENTER);
		removeFile.setText("Remove");
		removeFile.setToolTipText("Remove the last added file from the list.");
		gridData = new GridData();
		gridData.horizontalAlignment = SWT.END;

		removeFile.setLayoutData(gridData);

		removeFile.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				if (files.getItemCount() == 0) {
					return;
				}
				files.remove(files.getItemCount() - 1);
			}
		});

		final Button loadFile = new Button(associateFilesGroup, SWT.PUSH
				| SWT.RIGHT);
		loadFile.setAlignment(SWT.CENTER);
		loadFile.setText("Add..");
		loadFile.setToolTipText("Add any types of files from system, the "
				+ "absolute file path will be added to the list");

		loadFile.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				FileDialog file = new FileDialog(composite.getShell(), SWT.OPEN);
				file.setFilterExtensions(new String[] { "*.*" });
				file.setFilterNames(new String[] { "Associated files (*.*)" });
				file.setText("Load Associated File:");
				files.add(file.open());
				listCountLabel.setText(String.valueOf(files.getItemCount())
						+ " files loaded.");
			}
		});

		/*
		 * Use check box to control whether user wants to add associate file
		 * with Project
		 */
		associateFileCheckBox.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				loadFile.setEnabled(associateFileCheckBox.getSelection());
				removeFile.setEnabled(associateFileCheckBox.getSelection());
				files.setEnabled(associateFileCheckBox.getSelection());
				associateFileLabel.setEnabled(associateFileCheckBox
						.getSelection());
				selectedAssociates = associateFileCheckBox.getSelection();
				listCountLabel.setEnabled(associateFileCheckBox.getSelection());
			}
		});

		loadFile.setEnabled(associateFileCheckBox.getSelection());
		removeFile.setEnabled(associateFileCheckBox.getSelection());
		files.setEnabled(associateFileCheckBox.getSelection());
		associateFileLabel.setEnabled(associateFileCheckBox
				.getSelection());
		selectedAssociates = associateFileCheckBox.getSelection();
		listCountLabel.setEnabled(associateFileCheckBox.getSelection());

		return composite;
	}

	/**
	 * the data supplied to stored into local variable to be extracted using the
	 * get method by the CreateModelVersionAction class. This method checks to
	 * make sure that all the fields are filled out
	 * 
	 */
	@Override
	protected void okPressed() {

		modelVersionName = modelVersionNameText.getText();
		modelVersionCreator = modelVersionCreatorText.getText();
		modelVersionDescription = modelVersionDescriptionText.getText();

		if (modelVersionName.isEmpty()) {
			MessageDialog.openError(getShell(), "Invalid Model Version Name",
					"Please fill in the Model Version name.");
			return;
		}

		if (modelVersionCreator.isEmpty()) {
			MessageDialog.openError(getShell(),
					"Invalid Model Version Creator",
					"Please fill in the creator for the Model Version.");
			return;
		}

		if (modelVersionDescription.isEmpty()) {
			if (!MessageDialog
					.openConfirm(getShell(), "Empty Model Version Description",
							"Is it OK to leave description empty for now?")) {
				return;
			}
		}

		if (selected) {
			sourceFile = sourceFileText.getText();
			jarFile = jarFileText.getText();
			if (sourceFile.equals("")) {
				MessageDialog.openError(getShell(),
						"Invalid Source File Selection",
						"Please choose the source file.");
				return;
			}
			// if chose to load alp file and not yet specified input jar files
			if (jarFile.equals("") && sourceFile.endsWith("alp")) {
				MessageDialog
						.openConfirm(getShell(), "Invalid Jar File Selection",
								"Please choose the jar file created for this ModelProject.");
				return;
			}
		}

		if (selectedAssociates) {
			File temp;
			if (files.getItemCount() == 0) {
				if (MessageDialog
						.openConfirm(
								this.getParentShell(),
								"Non Associate Files listed",
								"You checked to add associate files but did not add any to the list. OK to proceed?")) {
					selectedAssociates = false;
				} else {
					return;
				}
			} else {
				// check if files can be loaded
				for (int index = 0; index < files.getItemCount(); index++) {
					temp = new File(files.getItem(index));
					if (!temp.canRead()) {
						MessageDialog.openError(
								getShell(),
								"File Open Error",
								"Unable to open Associated File at "
										+ files.getItem(index));
						return;
					}
				}
			}

			associateFiles = files.getItems();
		}

		super.okPressed();

	}/* end of OK pressed */

	/**
	 * a method to get the new model version name
	 * 
	 * @return String containing the version name
	 */
	public String getmodelVersionName() {
		return modelVersionName;
	}

	/**
	 * a method to get the new model version creator
	 * 
	 * @return String containing the version creator
	 */
	public String getmodelVersionCreator() {
		return modelVersionCreator;
	}

	/**
	 * a method to get the new model version description
	 * 
	 * @return String containing the version description
	 */
	public String getmodelVersionDescription() {
		return modelVersionDescription;
	}

	/**
	 * this method returns the selection of check box for input file group.
	 * Different ModelVersion creation method is initiated based on the user
	 * choice.
	 * 
	 * @return Boolean - whether check box is checked
	 */
	public Boolean getSelection() {
		return selected;
	}

	/**
	 * this method returns the selection of check box for associate file group.
	 * Different ModelVersion creation method is initiated based on the user
	 * choice.
	 * 
	 * @return Boolean - whether check box is checked
	 */
	public Boolean getAssociateFileSelection() {
		return selectedAssociates;
	}

	/**
	 * a method to get the new model version source file location
	 * 
	 * @return String containing the version source file location
	 */
	public String getSoureFilePath() {
		return sourceFile;
	}

	/**
	 * a method to get the new model version jar file location
	 * 
	 * @return String containing the version jar file location
	 * 
	 *         THIS SHOULD BE CHANGED TO DEAL WITH OTHER ASSOCIATED FILES
	 */
	public String getJarFilePath() {
		return jarFile;
	}

	/**
	 * a method to get the array of Strings containing a stack of associate file
	 * paths.
	 * 
	 * @return String[] containing a set of String; return null if no associate
	 *         files are added.
	 */
	public String[] getAssociateFileArray() {
		return associateFiles;
	}

	public ModelProjectID getParentModelProjectId() {
		return (ModelProjectID) modelprojectid;
	}

}